﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AutomatasPrj
{
    class AFND
    {
        protected Estado inicial;
        protected Estado[] estados;
        protected Estado[] finales;
        protected DeltaAFND delta;

        public AFND(Estado inicial,
                    Estado[] estados,
                    DeltaAFND delta,
                    Estado[] finales)
        {
            this.inicial = inicial;
            this.estados = estados;
            this.delta = delta;
            this.finales = finales;
        }

        public Estado Inicial { get { return inicial; } }

        public Estado[] Finales { get { return finales; } }

        public DeltaAFND Delta { get { return delta; } }

        public virtual bool Accepts(String palabra)
        {
            HashSet<Estado> ejecuciones = deltaGorro(inicial, palabra);

            // Si ejecuciones contiene al menos un estado final
            return (ejecuciones.Intersect(finales).Count() != 0);
        }

        public virtual HashSet<Estado> deltaGorro(Estado estado, String palabra)
        {
            //Caso base
            if (palabra.Length == 1)
                return delta.Evaluate(estado, Char.Parse(palabra));

            //Palabra = wa
            String w = palabra.Substring(0, palabra.Length-1);
            char a = Char.Parse(palabra.Substring(palabra.Length-1, 1));

            //Calculamos deltaGorro(estado, w) ..Caso recursivo
            HashSet<Estado> deltaGorroW = deltaGorro(estado, w);

            //Por cada estado r de deltaGorro(estado,w) hacemos la union delta(r,a)
            HashSet<Estado> unitatoria = new HashSet<Estado>();

            foreach (Estado r in deltaGorroW)
            {
                unitatoria.UnionWith(delta.Evaluate(r, a));
            }

            return unitatoria;

        }

        //public AFD ToAFD()
        //{
        //    HashSet<Estado> Qd = SetUtils<Estado>.PowerSet(estados);

        //    Estado inicialAFD = new Estado(delta.ClausuraEpsilon(this.inicial));

        //    DeltaAFD deltaAFD = new DeltaAFD();

        //    AFD afd = new AFD(inicialAFD, deltaAFD, finalesAFD);

        //    return afd;
        //}
    }
}
